<script setup lang='ts'>
import {
	computed,
	nextTick,
	onMounted,
	onUpdated,
	onUnmounted,
	ref
} from "vue";
import {
	NForm,
	FormInst,
	NFormItem,
	NInput,
	NButton,
	NPopover,
	useMessage
} from "naive-ui";
import { useScroll } from "../hooks/useScroll";
import { useBasicLayout } from "@/hooks/useBasicLayout";
import { useChatStore } from "@/store";
import { fetchChatAPI, fetchChatMessageAPI, fetchChatAPIProcess } from "@/api";
import { SvgIcon } from "@/components/common";
import * as emoji from "node-emoji";
import MarkdownIt from "markdown-it";
import mdKatex from "@traptitech/markdown-it-katex";
import mila from "markdown-it-link-attributes";
import hljs from "highlight.js";
import { t } from "@/locales";
import { copyToClip } from "@/utils/copy";

// debugger
let controller = new AbortController();

const message = useMessage();
const chatStore = useChatStore();
const { isMobile } = useBasicLayout();
const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom } = useScroll();

const loading = ref<boolean>(false);
const chatNumber = ref<string>("");
const formRef = ref<FormInst | null>(null);
const textRef = ref<HTMLElement>();
const text = ref<string>("");
const showPrompt = ref(false);
const showLoading = ref<boolean>(false);

const formValue = ref<any>({
	subject: "",
	text1: "",
	text2: "",
	text3: "",
	text4: "",
	text5: "",
	text6: "",
	text7: "",
	text8: "",
	text9: ""
});

const disabled = computed(() => {
	return !(
		formValue.value?.subject.trim() &&
		(formValue.value?.text1.trim() ||
			formValue.value?.text2.trim() ||
			formValue.value?.text3.trim() ||
			formValue.value?.text4.trim() ||
			formValue.value?.text5.trim() ||
			formValue.value?.text6.trim() ||
			formValue.value?.text7.trim() ||
			formValue.value?.text8.trim() ||
			formValue.value?.text9.trim())
	);
});

const rules = {
	subject: {
		required: true,
		message: "请输入工法名称",
		trigger: ["input", "blur"]
	}
};

// 内容样式
const indexClass = computed(() => {
	let classes = ["w-[700px]"];
	if (isMobile.value) classes = ["w-full", "overflow-hidden"];
	return classes;
});

const promptClass = computed(() => {
	let classes = ["w-[650px]"];
	if (isMobile.value) classes = ["w-full", "overflow-hidden"];
	return classes;
});

// 禁止代码调试
// (() => {
//   function block() {
//     if (window.outerHeight - window.innerHeight > 200 || window.outerWidth - window.innerWidth > 200) {
//       document.body.innerHTML = "检测到非法调试,请关闭后刷新重试!";
//     }
//     setInterval(() => {
//       (function () {
//         return false;
//       }
//       ['constructor']('debugger')
//       ['call']());
//     }, 50);
//   }
//   try {
//     block();
//   } catch (err) { }
// })();

onMounted(() => {
	addCopyEvents();
});

onUpdated(() => {
	addCopyEvents();
});

onUnmounted(() => {
	if (loading.value) {
		controller.abort();
	}
	removeCopyEvents();
});

// 处理带表情文字
function parseEmoji(str: string) {
	return emoji.emojify(str);
}

// 一键优化
async function handleSubmit() {
	if (loading.value) return;
	let prompt = `你是一名企业科技管理人员，根据要求优化工法前言、工法特点、适用范围、工艺原理、工艺流程及操作要点、材料与设备、质量控制、安全措施、环保措施。
  工法名称为：${formValue.value.subject}\n 注意：工法名称不需要优化。
  要求字数多,至少要比目前的字数多 文字专业, 应专业、具体进行表达，请根据工法名称进行填写以下内容:`;
	if (formValue.value.text1) {
		prompt =
			prompt + `工法前言：[${formValue.value.text1}]\n`;
	}
	if (formValue.value.text2) {
		prompt = prompt + `工法特点：[${formValue.value.text2}]\n`;
	}
	if (formValue.value.text3) {
		prompt = prompt + `适用范围：[${formValue.value.text3}]\n`;
	}
	if (formValue.value.text4) {
		prompt = prompt + `工艺原理：[${formValue.value.text4}]\n`;
	}
	if (formValue.value.text5) {
		prompt = prompt + `工艺流程及操作要点：[${formValue.value.text5}]\n`;
	}
	if (formValue.value.text6) {
		prompt = prompt + `材料与设备：[${formValue.value.text6}]\n`;
	}
	if (formValue.value.text7) {
		prompt = prompt + `质量控制：[${formValue.value.text7}]\n`;
	}
	if (formValue.value.text8) {
		prompt = prompt + `安全措施：[${formValue.value.text8}]\n`;
	}
	if (formValue.value.text9) {
		prompt = prompt + `环保措施：[${formValue.value.text9}]\n`;
	}
	fetchChat(prompt);
}

// 指定优化
async function handlePrompt(type: number) {
	if (loading.value) return;
	let prompt = `你是一名企业科技管理人员，根据要求优化工法前言或者工法特点或者适用范围或者工艺原理或者工艺流程及操作要点或者材料与设备或者质量控制或者安全措施或者环保措施。
  工法名称为：${formValue.value.subject}\n 注意：工法名称不需要优化。
  要求字数多,至少要比目前的字数多 文字专业, 应专业、具体进行表达，请根据工法名称进行填写以下内容:`;
	let content = "";
	let value = "";
	if (type == 1) {
		content = `工法前言：[${formValue.value.text1}]`;
		value = formValue.value.text1;
	} else if (type == 2) {
		content = `工法特点：[${formValue.value.text2}]`;
		value = formValue.value.text2;
	} else if (type == 3) {
		content = `适用范围：[${formValue.value.text3}]`;
		value = formValue.value.text3;
	} else if (type == 4) {
		content = `工艺原理：[${formValue.value.text4}]`;
		value = formValue.value.text4;
	} else if (type == 5) {
		content = `工艺流程及操作要点：[${formValue.value.text5}]`;
		value = formValue.value.text5;
	} else if (type == 6) {
		content = `材料与设备：[${formValue.value.text6}]`;
		value = formValue.value.text6;
	} else if (type == 7) {
		content = `质量控制：[${formValue.value.text7}]`;
		value = formValue.value.text7;
	} else if (type == 8) {
		content = `安全措施：[${formValue.value.text8}]`;
		value = formValue.value.text8;
	} else if (type == 9) {
		content = `环保措施：[${formValue.value.text9}]`;
		value = formValue.value.text9;
	}
	if (!value || value == "") {
		message.warning("内容为空，无法优化");
		return;
	}

	prompt = prompt + content;
	fetchChat(prompt);
}

/** 发送聊天请求 */
async function fetchChat(message: string) {
	loading.value = true;
	showLoading.value = true;
	showPrompt.value = false;
	const chatData: Chat.ChatRequest = {
		systemPrompt: message,
		prompt: message
	};
	// 创建会话
	if (!chatNumber.value) {
		const chatRes = await fetchChatAPI(chatData);
		chatNumber.value = chatRes.data.chatNumber;
		await nextTick();
	}
	const messageData: Chat.MessageRequest = {
		chatNumber: chatNumber.value,
		model: chatStore.model,
		systemPrompt: message,
		prompt: message
	};
	// 发送内容
	const messageRes = await fetchChatMessageAPI(messageData);
	// 流式响应
	onConversation(chatNumber.value, messageRes.data);
}

/**
 * sse对话
 */
async function onConversation(chatNumber: string, conversationId: string) {
	controller = new AbortController();
	try {
		let lastText = "";
		text.value = "";
		const fetchChatAPIOnce = async () => {
			await fetchChatAPIProcess<Chat.ConversationResponse>({
				conversationId: conversationId,
				signal: controller.signal,
				onDownloadProgress: ({ event }) => {
					const xhr = event.target;
					const { responseText } = xhr;
					const lastIndex = responseText.lastIndexOf(
						"\n",
						responseText.length - 2
					);
					let chunk = responseText;
					if (lastIndex !== -1) {
						chunk = responseText.substring(lastIndex);
					}
					try {
						const data = JSON.parse(chunk);
						showLoading.value = false;
						showPrompt.value = true;
						text.value = lastText + (data.content ?? "");
						scrollToBottom();
					} catch (error) {
						console.info("回复错误:", error);
					}
				}
			});
		};
		await fetchChatAPIOnce();
	} catch (error) {
		text.value = "大模型回复失败";
	} finally {
		loading.value = false;
		showLoading.value = false;
		scrollToBottomIfAtBottom();
	}
}

/** 重新回复 */
// async function onRegenerate(messageId?: string | null) {
//   if (!messageId) return;
//   fetchChatMessageById(messageId).then((res: { data: { content: string } }) => {
//     prompt.value = res.data.content;
//     handleSubmit();
//   });
// }

const textValue = computed(() => {
	const value = text.value ?? "";
	return mdi.render(value);
});

const mdi = new MarkdownIt({
	html: false,
	linkify: true,
	highlight(code, language) {
		const validLang = !!(language && hljs.getLanguage(language));
		if (validLang) {
			const lang = language ?? "";
			return highlightBlock(
				hljs.highlight(code, { language: lang }).value,
				lang
			);
		}
		return highlightBlock(hljs.highlightAuto(code).value, "");
	}
});

mdi.use(mila, { attrs: { target: "_blank", rel: "noopener" } });
mdi.use(mdKatex, {
	blockClass: "katexmath-block rounded-md p-[10px]",
	errorColor: " #cc0000"
});

function highlightBlock(str: string, lang?: string) {
	return `<pre class="code-block-wrapper"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">${t(
		"chat.copyCode"
	)}</span></div><code class="hljs code-block-body ${lang}">${str}</code></pre>`;
}

async function handleCopy() {
	try {
		await copyToClip(text.value || "");
		message.success("复制成功");
	} catch {
		message.error("复制失败");
	}
}

function addCopyEvents() {
	if (textRef.value) {
		const copyBtn = textRef.value.querySelectorAll(".code-block-header__copy");
		copyBtn.forEach(btn => {
			btn.addEventListener("click", () => {
				const code = btn.parentElement?.nextElementSibling?.textContent;
				if (code) {
					copyToClip(code).then(() => {
						btn.textContent = "复制成功";
						setTimeout(() => {
							btn.textContent = "复制代码";
						}, 1000);
					});
				}
			});
		});
	}
}

function removeCopyEvents() {
	if (textRef.value) {
		const copyBtn = textRef.value.querySelectorAll(".code-block-header__copy");
		copyBtn.forEach(btn => {
			btn.removeEventListener("click", () => {});
		});
	}
}
</script>
<style lang="less">
@import url(../components/message/style.less);
</style>

<style scoped>
.input-form {
	border-radius: 8px;
	width: 380px;
}

.login-form {
	height: 45px;
	width: 600px;
	border-radius: 8px;
	font-size: 17px;
	font-weight: 500;
	display: flex;
	align-items: center;
}

/* 通用滚动条样式 */
::-webkit-scrollbar {
	width: 10px; /* 宽度 */
}

/* 滚动条轨道 */
::-webkit-scrollbar-track {
	background-color: rgba(0, 0, 0, 0.1); /* 轨道颜色 */
}
/* 鼠标悬停时的滑块 */
::-webkit-scrollbar-thumb:hover {
	background-color: rgba(45, 44, 44, 0.7); /* 滑块悬停颜色 */
}
</style>
<template>
	<div class="flex-col w-full h-full bg-slate-50 dark:bg-[#18181c]">
		<div class="h-20 pl-8 text-xl flex items-center">
			<!-- <img :src="logom" class="w-8 h-8 mr-2" /> -->
			<span>科研项目优化与分析</span>
		</div>
		<div class="flex mt-6">
			<!-- 表单填充 -->
			<div
				class="flex-col h-full bg-white dark:bg-[#24272e] mx-auto px-8 py-8 rounded-xl"
				:class="indexClass"
			>
				<div class="text-center text-3xl font-medium mb-2">工法</div>
				<div class="text-center text-[15px] text-[#909090] mb-8">填写基础的内容信息，帮你快速优化工法相关文字。</div>

				<NForm
					ref="formRef"
					:model="formValue"
					:rules="rules"
					label-placement="left"
					label-width="auto"
				>

					<div>
						<NFormItem label="工法名称" path="subject">
							<NInput
								class="input-form"
								type="textarea"
								v-model:value="formValue.subject"
								placeholder="请输入工法名称"
								:rows="1"
							/>
						</NFormItem>
					</div>
					<div style="height: 51vh;overflow-y: auto;">
					<div class="flex items-center">
						<NFormItem label="前言">
							<NInput
								class="input-form"
								type="textarea"
								v-model:value="formValue.text1"
								placeholder="请输入工法前言"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(1)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="工法特点">
							<NInput
								class="input-form"
								v-model:value="formValue.text2"
								type="textarea"
								placeholder="请输入工法特点"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(2)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="适用范围">
							<NInput
								class="input-form"
								v-model:value="formValue.text3"
								type="textarea"
								placeholder="请输入适用范围"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(3)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="工艺原理">
							<NInput
								class="input-form"
								v-model:value="formValue.text4"
								type="textarea"
								placeholder="请输入工艺原理"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(4)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="工艺流程及操作要点">
							<NInput
								class="input-form"
								v-model:value="formValue.text5"
								type="textarea"
								placeholder="请输入工艺流程及操作要点"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(5)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="材料与设备">
							<NInput
								class="input-form"
								v-model:value="formValue.text6"
								type="textarea"
								placeholder="请输入材料与设备"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(6)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="质量控制">
							<NInput
								class="input-form"
								v-model:value="formValue.text7"
								type="textarea"
								placeholder="请输入质量控制"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(7)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="安全措施">
							<NInput
								class="input-form"
								v-model:value="formValue.text8"
								type="textarea"
								placeholder="请输入安全措施"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(8)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					<div class="flex items-center">
						<NFormItem label="环保措施">
							<NInput
								class="input-form"
								v-model:value="formValue.text9"
								type="textarea"
								placeholder="请输入环保措施"
							/>
						</NFormItem>
						<NPopover
							raw
							trigger="hover"
							:show-arrow="true"
							:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
						>
							<template #trigger>
								<div
									class="ml-3 flex items-center justify-center w-[32px] h-[32px] bg-blue-50 dark:bg-[#24272e] rounded-2xl cursor-pointer"
									@click="handlePrompt(9)"
								>
									<SvgIcon icon="ri:send-plane-fill" class="text-2xl text-blue-600 mr-[3px]" />
								</div>
							</template>
							<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">优化</div>
						</NPopover>
					</div>
					</div>


					<div class="flex justify-center">
						<NButton
							class="login-form"
							block
							type="primary"
							@click="handleSubmit()"
							:disabled="disabled"
							:loading="loading"
						>
							一键优化
							<SvgIcon icon="ri:check-line" style="color: #fff; margin-left:10px" />
						</NButton>
					</div>
				</NForm>


			</div>
			<div
				class="flex-col h-full bg-white dark:bg-[#24272e] mx-auto px-10 py-8 rounded-xl"
				:class="promptClass"
			>
				<div class="text-center text-3xl font-medium mb-2">AI优化{{ parseEmoji(':fire:') }}</div>
				<div class="text-center text-[15px] text-[#909090] mb-8">优化完成可复制下方内容，如不满意可以重新填写或选择重新优化。</div>
				<template v-if="showPrompt">
					<div
						id="scrollRef"
						ref="scrollRef"
						class="h-[510px] overflow-hidden overflow-y-auto no-scrollbar"
					>
						<div ref="textRef" class="leading-7 break-words text-[15px]">
							<div class="markdown-body" v-html="textValue" />
						</div>
					</div>
					<div class="flex justify-between mt-4">
						<div class="text-[#B0B7C0] text-xs">以上内容为AI生成，请自行辨别</div>
						<div>
							<NPopover
								raw
								trigger="hover"
								:show-arrow="true"
								:arrow-style="{ backgroundColor: 'rgb(100 116 139)' }"
							>
								<template #trigger>
									<button
										class="text-[18px] text-neutral-300 hover:text-neutral-800 dark:hover:text-neutral-300"
										style="margin: 0;"
										@click="handleCopy"
									>
										<SvgIcon icon="ri:file-copy-2-line" />
									</button>
								</template>
								<div class="px-3 py-2 bg-slate-500 text-[#fff] rounded-md">复制</div>
							</NPopover>
						</div>
					</div>
				</template>
				<template v-else>
					<div class="w-full h-[574px] flex flex-col items-center justify-center">
						<template v-if="showLoading">
							<img src="@/assets/loading.gif" class="w-[300px] h-[300px]" />
						</template>
						<template v-else>
							<img src="@/assets/optimize.png" class="w-[380px] h-[320px]" />
							<div class="text-[#909090]">请在左侧输入内容，开始优化</div>
						</template>
					</div>
				</template>
			</div>
		</div>
	</div>
</template>
